#include <stdint.h>
#include "typedef.h"
//#include "oobw_fsm.h"
#include "oobw_statemachine.h"

__weak void vST00Entry_OOBW(void)  { }
__weak void vST00Action_OOBW(void) { }
__weak void vST00Exit_OOBW(void)  { }

__weak void vST01Entry_OOBW(void)  { }
__weak void vST01Action_OOBW(void) { }
__weak void vST01Exit_OOBW(void) { }

__weak void vST02Entry_OOBW(void)  { }
__weak void vST02Action_OOBW(void) { }
__weak void vST02Exit_OOBW(void) { }

__weak void vST03Entry_OOBW(void)  { }
__weak void vST03Action_OOBW(void) { }
__weak void vST03Exit_OOBW(void) { }


__weak void vST04Entry_OOBW(void)  { }
__weak void vST04Action_OOBW(void) { }
__weak void vST04Exit_OOBW(void) { }


__weak void vST05Entry_OOBW(void)  { }
__weak void vST05Action_OOBW(void) { }
__weak void vST05Exit_OOBW(void) { }


__weak void vST06Entry_OOBW(void)  { }
__weak void vST06Action_OOBW(void) { }
__weak void vST06Exit_OOBW(void) { }

__weak void vST07Entry_OOBW(void)  { }
__weak void vST07Action_OOBW(void) { }
__weak void vST07Exit_OOBW(void) { }

__weak void vST08Entry_OOBW(void)  { }
__weak void vST08Action_OOBW(void) { }
__weak void vST08Exit_OOBW(void) { }

__weak bool bCheckTR00_OOBW(void) { return false; }
__weak bool bCheckTR01_OOBW(void) { return false; }
__weak bool bCheckTR02_OOBW(void) { return false; }
__weak bool bCheckTR03_OOBW(void) { return false; }
__weak bool bCheckTR04_OOBW(void) { return false; }
__weak bool bCheckTR05_OOBW(void) { return false; }
__weak bool bCheckTR06_OOBW(void) { return false; }
__weak bool bCheckTR07_OOBW(void) { return false; }
__weak bool bCheckTR08_OOBW(void) { return false; }
__weak bool bCheckTR09_OOBW(void) { return false; }
__weak bool bCheckTR10_OOBW(void) { return false; }
__weak bool bCheckTR11_OOBW(void) { return false; }
__weak bool bCheckTR12_OOBW(void) { return false; }
__weak bool bCheckTR13_OOBW(void) { return false; }
__weak bool bCheckTR14_OOBW(void) { return false; }
__weak bool bCheckTR15_OOBW(void) { return false; }
__weak bool bCheckTR16_OOBW(void) { return false; }
__weak bool bCheckTR17_OOBW(void) { return false; }
__weak bool bCheckTR18_OOBW(void) { return false; }
__weak bool bCheckTR19_OOBW(void) { return false; }
__weak bool bCheckTR20_OOBW(void) { return false; }
__weak bool bCheckTR21_OOBW(void) { return false; }
__weak bool bCheckTR22_OOBW(void) { return false; }

//-------------------------------------------------------------------------------------//
//                           Structures
//-------------------------------------------------------------------------------------//
typedef struct           // TState
{
  const char* szName;
  unsigned short usId;
  void   (*vEntry)(void);
  void   (*vAction)(void);
  void   (*vExit)(void);
}TState;

typedef struct           // TTransition
{
  const TState  *ptCurrentState;
  const TState  *ptNextState;
  bool         (*bCheck)(void);
} TTransition;

typedef struct           // TStateMachine
{
  const TState      *ptCurrentState;
  const TState      *ptStateList;
  unsigned short     usStateCount;
  const TTransition *ptTransList;
  unsigned short     usTransCount;
} TStateMachine;



////------------------------------------------------------------------------------------------------//
////  Control StateMachine Init
////------------------------------------------------------------------------------------------------//
static const TState  tMotorCtrlStateListOOBW[US_OOBW_MAX_STATE_NUMBER] =
{
//    Name       ID   Entry            Action            Exit
    {" Idle "    , 0, &vST00Entry_OOBW, &vST00Action_OOBW, &vST00Exit_OOBW},
    {" OOB_StrP" , 1, &vST01Entry_OOBW, &vST01Action_OOBW, &vST01Exit_OOBW},
    {" OOB_Acc"  , 2, &vST02Entry_OOBW, &vST02Action_OOBW, &vST02Exit_OOBW},
    {" OOB_Chk"  , 3, &vST03Entry_OOBW, &vST03Action_OOBW, &vST03Exit_OOBW},
    {" We_Acc"   , 4, &vST04Entry_OOBW, &vST04Action_OOBW, &vST04Exit_OOBW},
    {" We_Hold"  , 5, &vST05Entry_OOBW, &vST05Action_OOBW, &vST05Exit_OOBW},
    {" We_DAcc"  , 6, &vST06Entry_OOBW, &vST06Action_OOBW, &vST06Exit_OOBW},
    {" DONE"     , 7, &vST07Entry_OOBW, &vST07Action_OOBW, &vST07Exit_OOBW},
    {" FAULT"    , 8, &vST08Entry_OOBW, &vST08Action_OOBW, &vST08Exit_OOBW},
};
// Transitions List for Input Global State Machine
static const TTransition tMotorCtrlStateTransListOOBW[US_OOBW_MAX_TRANS_NUMBER] =
{
//    CurrentState               ptNextState               Transition
    {&tMotorCtrlStateListOOBW[0], &tMotorCtrlStateListOOBW[1], &bCheckTR00_OOBW},
    {&tMotorCtrlStateListOOBW[1], &tMotorCtrlStateListOOBW[2], &bCheckTR01_OOBW},
    {&tMotorCtrlStateListOOBW[2], &tMotorCtrlStateListOOBW[3], &bCheckTR02_OOBW},
    {&tMotorCtrlStateListOOBW[3], &tMotorCtrlStateListOOBW[4], &bCheckTR03_OOBW},
    {&tMotorCtrlStateListOOBW[4], &tMotorCtrlStateListOOBW[5], &bCheckTR04_OOBW},
    {&tMotorCtrlStateListOOBW[5], &tMotorCtrlStateListOOBW[6], &bCheckTR05_OOBW},
    {&tMotorCtrlStateListOOBW[6], &tMotorCtrlStateListOOBW[3], &bCheckTR06_OOBW},
    {&tMotorCtrlStateListOOBW[3], &tMotorCtrlStateListOOBW[7], &bCheckTR07_OOBW},
    {&tMotorCtrlStateListOOBW[0], &tMotorCtrlStateListOOBW[2], &bCheckTR08_OOBW},
    {&tMotorCtrlStateListOOBW[1], &tMotorCtrlStateListOOBW[0], &bCheckTR09_OOBW},
    {&tMotorCtrlStateListOOBW[2], &tMotorCtrlStateListOOBW[0], &bCheckTR10_OOBW},
    {&tMotorCtrlStateListOOBW[3], &tMotorCtrlStateListOOBW[0], &bCheckTR11_OOBW},
    {&tMotorCtrlStateListOOBW[4], &tMotorCtrlStateListOOBW[0], &bCheckTR12_OOBW},
    {&tMotorCtrlStateListOOBW[5], &tMotorCtrlStateListOOBW[0], &bCheckTR13_OOBW},
    {&tMotorCtrlStateListOOBW[6], &tMotorCtrlStateListOOBW[0], &bCheckTR14_OOBW},
    {&tMotorCtrlStateListOOBW[7], &tMotorCtrlStateListOOBW[0], &bCheckTR15_OOBW},
    {&tMotorCtrlStateListOOBW[8], &tMotorCtrlStateListOOBW[0], &bCheckTR16_OOBW},
    {&tMotorCtrlStateListOOBW[1], &tMotorCtrlStateListOOBW[8], &bCheckTR17_OOBW},
    {&tMotorCtrlStateListOOBW[2], &tMotorCtrlStateListOOBW[8], &bCheckTR18_OOBW},
    {&tMotorCtrlStateListOOBW[3], &tMotorCtrlStateListOOBW[8], &bCheckTR19_OOBW},
    {&tMotorCtrlStateListOOBW[4], &tMotorCtrlStateListOOBW[8], &bCheckTR20_OOBW},
    {&tMotorCtrlStateListOOBW[5], &tMotorCtrlStateListOOBW[8], &bCheckTR21_OOBW},
    {&tMotorCtrlStateListOOBW[6], &tMotorCtrlStateListOOBW[8], &bCheckTR22_OOBW},
};

// Input Global State Machine
static TStateMachine tMotorCtrlStateOOBW =
{
    &tMotorCtrlStateListOOBW[0],        // Current state
    &tMotorCtrlStateListOOBW[0],        // State list
    US_OOBW_MAX_STATE_NUMBER,           // State count
    &tMotorCtrlStateTransListOOBW[0],   // Transition list
    US_OOBW_MAX_TRANS_NUMBER            // Transition count
};


void vInitialStateMachine(void)
{
    tMotorCtrlStateOOBW.ptCurrentState = tMotorCtrlStateListOOBW;
    tMotorCtrlStateOOBW.ptStateList    = tMotorCtrlStateListOOBW;
    tMotorCtrlStateOOBW.ptTransList    = tMotorCtrlStateTransListOOBW;
    tMotorCtrlStateOOBW.usStateCount   = US_OOBW_MAX_STATE_NUMBER;
    tMotorCtrlStateOOBW.usTransCount   = US_OOBW_MAX_TRANS_NUMBER;
}

void vProcessTransitions(void)
{
    unsigned short  i               = 0;
    bool            ret             = 0;
    TStateMachine        *ptStateMachine  = &tMotorCtrlStateOOBW;
    const TState         *pCurstate       = ptStateMachine->ptCurrentState;          
    //const TState         *pStateList    = ptStateMachine->ptStateList;
    const TTransition    *pTransList      = ptStateMachine->ptTransList;
    
    unsigned short  usTransCount    = ptStateMachine->usTransCount;
    
    for(i = 0; i < usTransCount; i++) {
        if(pCurstate == pTransList[i].ptCurrentState) {
            ret = pTransList[i].bCheck();
            if(ret == true) {
                ptStateMachine->ptCurrentState->vExit();
                ptStateMachine->ptCurrentState = pTransList[i].ptNextState;
                ptStateMachine->ptCurrentState->vEntry();
                break;
            } 
        }
    }
}
void vExecuteCurrentState(void)
{
    TStateMachine        *ptStateMachine  = &tMotorCtrlStateOOBW;
    if(ptStateMachine != NULL) {
        if(ptStateMachine->ptCurrentState != NULL && ptStateMachine->ptCurrentState->vAction != NULL) {
            ptStateMachine->ptCurrentState->vAction();
        }
    }
}

